package com.example.shangguigu.signature;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.security.KeyFactory;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * @DESCRIPTION:
 * @USER: shg
 * @DATE: 2023/2/25 17:54
 */
public class SignatureDemo {

    public static void main(String[] args) throws Exception {

        // 明文数据
        String sourceData = "aa";
        String hashAlgorithm = "sha256withrsa";
        // RSA公钥
        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwCatefCcMklTYcfv/FVB8Q3vk03CNwif9de5Hy3xLHgXdSeH+0vbftj4wXz5C4H/cOxwXJiUcNXkLPFFIJVS+fLzdeHM7TB7BxEtGnY4O2kZBioolf2qSnlqTDyIYde8KtnmfDgpPxUGZV5befwZRgo244ygWB7FO731NcipZBwIDAQAB";
        // RSA私钥
        String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALAJq158JwySVNhx+/8VUHxDe+TTcI3CJ/117kfLfEseBd1J4f7S9t+2PjBfPkLgf9w7HBcmJRw1eQs8UUglVL58vN14cztMHsHES0adjg7aRkGKiiV/apKeWpMPIhh17wq2eZ8OCk/FQZlXlt5/BlGCjbjjKBYHsU7vfU1yKlkHAgMBAAECgYAUFtZmrvZp2d0y4jcm0hDgTXc7EuIaW1ji9O1fZhpmHCQBL+hJg1vHBe4s6QGa8jHFOT2oaqL7iCKrJJQGDrSP49f7/RJiR5EU6IHSRHowK/cUzgZ57/9ROVRva46DQPxEzcGlRTgOI7ajjIVmBDW03XN5+bCITiGh/HFmjKAEYQJBAOhSCENxWi6eBI11aQpuywwRJBNgAaPQqGzrfJQ8xPsWYV8d+U8QzH55IR9+egtrbvW0t4Xdu96iwnSn0Si4IXcCQQDB+wvM+N10VHbr6sDHGcQXWLioK9GN/rZQUgBnC5EKhcQBQZkevJtY92OKCq6sgN5EIhqwNdleFHdkXclNOejxAkBUXGVvyBuNTggtLfNkvHKzAQ5ukrBFwiFG3AQy+BY3bxsQpRvA4ELBsk6a1xyORQbX5jW2QJxV7hhasA29kY9lAkAHeUGqIwh9O+fdDQ1iXmbEs4Fh0VZgjyi9DXvAfJyY+DBmD/3zRjcCBX4LSoASW2C05U977Ic0bbtv3YEs/YcxAkANyGSIAH5PS1aUSLMD9NC9Yov+9AyJJY5P5CePwm1bDGcrq1kNQzUW3uYIL26u9D9wHdP7Ownj+XSshPc3ynk0";

        // 生成原始信息的数字签名
        String signatureData = generateSignature(sourceData, hashAlgorithm, privateKey);
        System.out.println("签名后的数据如下：\n"+signatureData);

        // 对签名进行验证
        boolean flag = verifySignature(sourceData,hashAlgorithm,publicKey,signatureData);
        System.out.println("验签结果：\n"+flag);

    }

    /**
     * 验证签名
     * @param sourceData    原始明文数据
     * @param hashAlgorithm 签名过程中使用的hash算法
     * @param publicKey     公钥
     * @param signatureData 签名后的数据
     * @return
     */
    private static boolean verifySignature(String sourceData, String hashAlgorithm, String publicKey, String signatureData) throws Exception{
        // 获取签名对象
        Signature signature = Signature.getInstance(hashAlgorithm);
        // 初始化签名
        byte[] bytes = new BASE64Decoder().decodeBuffer(publicKey);
        RSAPublicKey rsaPublicKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(bytes));
        signature.initVerify(rsaPublicKey);
        // 传入原文
        signature.update(sourceData.getBytes());
        // 校验签名

        return signature.verify(new BASE64Decoder().decodeBuffer(signatureData));
    }

    /**
     * 生成签名
     * @param sourceData    原始明文数据
     * @param hashAlgorithm 签名过程中使用的hash算法
     * @param privateKey    私钥
     * @return
     */
    private static String generateSignature(String sourceData, String hashAlgorithm, String privateKey) throws Exception{
        // 获取签名对象
        Signature signature = Signature.getInstance(hashAlgorithm);
        // 初始化签名
        byte[] privateBytes = new BASE64Decoder().decodeBuffer(privateKey);
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateBytes));
        signature.initSign(rsaPrivateKey);
        // 传入原文
        signature.update(sourceData.getBytes());
        // 开始签名
        byte[] sign = signature.sign();
        return new BASE64Encoder().encode(sign);
    }
}
